package com.coocaa.x.service.litewebserver.webserver.servlet;

import android.content.Context;
import android.util.Log;

import com.coocaa.x.app.framework.app.LiteAppApplication;
import com.coocaa.x.demo.servlets.AppServlet;
import com.coocaa.x.demo.servlets.CacheServlet;
import com.coocaa.x.demo.servlets.DefaultServlet;
import com.coocaa.x.demo.servlets.PlayerServlet;
import com.coocaa.x.demo.servlets.SDeviceServlet;
import com.coocaa.x.demo.servlets.WebDataServlet;
import com.coocaa.x.demo.servlets.WebServlet;
import com.coocaa.x.framework.app.CoocaaApplication;
import com.coocaa.x.framework.utils.Android;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by lu on 15-9-8.
 */
public class ServletLoader {

    private static Context mContext;
    public static abstract class AbstractServletLoader {
        public abstract List<Servlet.ServletInfo> loadServletInfos();

        public abstract Servlet loadServlet(Servlet.ServletInfo info);
    }

    private static final class CodeServletLoader extends AbstractServletLoader {
        protected static final String META_DATA_KEY = "servlets_class";
        private Map<String, Servlet> map = new HashMap<String, Servlet>();

        @Override
        public List<Servlet.ServletInfo> loadServletInfos() {
            List<Servlet.ServletInfo> ret = new ArrayList<Servlet.ServletInfo>();
            try {
                String clazzez = (String) Android.getMetaData(CoocaaApplication.getContext(), CoocaaApplication.getContext().getPackageName(), META_DATA_KEY);
                String[] clazzz = clazzez.split("\\|");
                for (String clazz : clazzz) {
//                    LogUtils.i("", "mContext 22:" + clazz);
//                    Servlet s;
//                    if(clazz.contains("AppServlet")){
//                        s = new AppServlet();
//                    }else if(clazz.contains("CacheServlet")){
//                        s = new CacheServlet();
//                    }else if(clazz.contains("DefaultServlet")){
//                        s = new DefaultServlet();
//                    }else if(clazz.contains("PlayerServlet")){
//                        s = new PlayerServlet();
//                    }else if(clazz.contains("SDeviceServlet")){
//                        s = new SDeviceServlet();
//                    }else if(clazz.contains("WebDataServlet")){
//                        s = new WebDataServlet();
//                    }else if(clazz.contains("WebServlet")){
//                        s = new WebServlet();
//                    }else{
//                        s = new WebServlet();
//                    }

                    Servlet s = (Servlet) Class.forName(clazz).newInstance();
                    s.setContext(mContext);
                    synchronized (map) {
                        Servlet.ServletInfo i = s.getServletInfo();
                        String id = i.getID();
                        if (map.containsKey(id)) {
                            for (Servlet.ServletInfo _i : ret) {
                                if (_i.getID().equals(id)) {
                                    ret.remove(_i);
                                    break;
                                }
                            }
                            map.remove(id);
                        }
                        map.put(s.getServletInfo().getID(), s);
                        ret.add(s.getServletInfo());
                    }
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
            return ret;
        }

        @Override
        public Servlet loadServlet(Servlet.ServletInfo info) {
            synchronized (map) {
                return map.get(info.getID());
            }
        }
    }

    public static interface ServletLoaderListener {
        void onLoadCompleted(List<Servlet> list);
    }

    private static ServletLoader instance = new ServletLoader();

    public static synchronized ServletLoader getLoader(Context context) {
        mContext = context;
        return instance;
    }


    private static final String DEFAULT_SERVLET_META_KEY = "default_servlet_class";
    private static final String CACHE_SERVLET_META_KEY = "cache_servlet_class";

    private static final AbstractServletLoader[] LOADERS = {new CodeServletLoader()};
    private ServletLoaderListener listener = null;
    private Thread loadThread = null;
    private Servlet defaultServlet = null;
    private Servlet cacheServlet = null;

    public void setListener(ServletLoaderListener l) {
        listener = l;
    }

    public synchronized void releaseServlet() {

    }

    public synchronized void loadServlet() {
        if (loadThread == null) {
            loadThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    Map<String, Servlet.ServletInfo> infoMap = new HashMap<String, Servlet.ServletInfo>();
                    Map<String, AbstractServletLoader> servletLoaderMap = new HashMap<String, AbstractServletLoader>();
                    List<Servlet> servlets = new ArrayList<Servlet>();
                    for (AbstractServletLoader loader : LOADERS) {
                        List<Servlet.ServletInfo> infos = loader.loadServletInfos();
                        for (Servlet.ServletInfo info : infos) {
                            if (infoMap.containsKey(info.getID()) && infoMap.get(info.getID()).versionCode < info.versionCode) {
                                infoMap.remove(info.getID());
                                servletLoaderMap.remove(info.getID());
                            }
                            if (!infoMap.containsKey(info.getID())) {
                                infoMap.put(info.getID(), info);
                                servletLoaderMap.put(info.getID(), loader);
                            }
                        }
                    }

                    Collection<Servlet.ServletInfo> infos = infoMap.values();
                    for (Servlet.ServletInfo info : infos) {
                        AbstractServletLoader loader = servletLoaderMap.get(info.getID());
                        if (loader != null) {
                            Servlet servlet = loader.loadServlet(info);
                            if (servlet != null) {
                                servlet.create();
                                servlets.add(servlet);
                            }
                        }
                    }
                    if (listener != null)
                        listener.onLoadCompleted(servlets);
                    infoMap.clear();
                    servletLoaderMap.clear();
                    servlets.clear();
                    loadThread = null;
                }
            });
            loadThread.start();
        }
    }

    public synchronized Servlet getCacheServlet() {
        if (cacheServlet == null) {
            try {
//                LogUtils.i("","mContext 11:"+mContext.getPackageName()+"; "+mContext.getClass().getName());
                String clazz = (String) Android.getMetaData(mContext.getApplicationContext(), mContext.getApplicationContext().getPackageName(), CACHE_SERVLET_META_KEY);

//                LogUtils.i("", "mContext 22:" + CoocaaApplication.getContext().getPackageName() + "; " + CoocaaApplication.getContext().getClass().getName()+"; "+clazz);
                cacheServlet = (Servlet) Class.forName(clazz).newInstance();
//                cacheServlet = new CacheServlet();
                cacheServlet.setContext(mContext);
                cacheServlet.create();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return cacheServlet;
    }

    public synchronized Servlet getDefaultServlet() {
        if (defaultServlet == null) {
            try {
//                LogUtils.i("","mContext 33:"+mContext.getPackageName()+"; "+mContext.getClass().getName());
                String clazz = (String) Android.getMetaData(mContext.getApplicationContext(), mContext.getApplicationContext().getPackageName(), DEFAULT_SERVLET_META_KEY);

//                LogUtils.i("","mContext 33:"+mContext.getApplicationContext().getPackageName()+"; "+mContext.getApplicationContext().getClass().getName()+"; "+mContext.getApplicationContext());
//                LogUtils.i("", "mContext 44:" + CoocaaApplication.getContext().getPackageName() + "; " + CoocaaApplication.getContext()+"; "+clazz);
                defaultServlet = (Servlet) Class.forName(clazz).newInstance();
//                defaultServlet = new DefaultServlet();
                defaultServlet.setContext(mContext);
                defaultServlet.create();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return defaultServlet;
    }
}
